package com.zb.jnlxc.viewResolver;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.*;

import com.zb.jnlxc.aop.StopWatchUtil;
import com.zb.jnlxc.form.MiniPageRsp;
import com.zb.util.StringUtils;
import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.log4j.MDC;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.zb.jnlxc.constants.JsonConst;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

public class MappingGsonConverter extends AbstractHttpMessageConverter<Object> {

    Logger RESULTLOGGER = LoggerFactory
            .getLogger(MappingGsonConverter.class);

    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

    public Map<String,JSONObject> jsonCache = new HashMap<String, JSONObject>();


    /**
     * Construct a new {@code BindingJacksonHttpMessageConverter}.
     */
    public MappingGsonConverter() {
        super(new MediaType("application", "json", DEFAULT_CHARSET));
    }

    @Override
    public boolean canRead(Class<?> clazz, MediaType mediaType) {
        return (canRead(mediaType));
    }

    @Override
    public boolean canWrite(Class<?> clazz, MediaType mediaType) {
        return (canWrite(mediaType));
    }

    @Override
    protected boolean supports(Class<?> clazz) {
        throw new UnsupportedOperationException();
    }

    @Override
    protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage)
    throws IOException,
                                                                                HttpMessageNotReadableException {
        return null;
    }

    @Override
    protected void writeInternal(Object object, HttpOutputMessage outputMessage)
                                                                                throws IOException,
                                                                                HttpMessageNotWritableException {
        Object result = object;
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes()).getRequest();
        String jsonFormate = request.getParameter("jsonFormate");
        try {

            if (StringUtils.isNotBlank(jsonFormate)) {

                String servletPath = request.getServletPath();
                JSONObject jsonObject = jsonCache.get(servletPath);
                if(jsonObject==null){
                    jsonObject = JSONObject.parseObject(jsonFormate);
//                    jsonCache.put(servletPath,jsonObject);
                }
                if (object instanceof List) {
                    List<JSONObject> jsons = new ArrayList<JSONObject>();
                    for (Object item : (List) object) {
                        JSONObject js = (JSONObject) jsonObject.clone();
                        copyProperties(item,js,null);
                        jsons.add(js);
                    }
                    result = jsons;
                } else if (object instanceof MiniPageRsp) {
                    List<JSONObject> jsons = new ArrayList<JSONObject>();
                    for (Object item : ((MiniPageRsp) object).getData()) {
                        JSONObject js = (JSONObject) jsonObject.clone();
                        copyProperties(item,js,null);
                        jsons.add(js);
                    }
                    result = jsons;
                } else {
                    JSONObject js = (JSONObject) jsonObject.clone();
                    copyProperties(object,js,null);
                    result = js;
                }
            }
        }catch (Exception e){
            RESULTLOGGER.error("格式化出错",e);
        }

        String jsonResponse = JSONObject.toJSONString(result, JsonConst.defaultConfig,
            SerializerFeature.DisableCircularReferenceDetect);
        long costTime = StopWatchUtil.getTotalTime();
        MDC.put("costTime",costTime);
        if(jsonResponse.length()<=1000){
            RESULTLOGGER.info("【结果】耗时={}ms, requestUri = {}, response={}",new String[]{costTime+"",request.getServletPath(), jsonResponse});
        }else {
            RESULTLOGGER.info("【结果】 耗时={}ms, requestUri = {}, response={}", new String[]{costTime+"",request.getServletPath(), jsonResponse.substring(0,1000)+"......"});
        }
        outputMessage.getBody().write(jsonResponse.getBytes("utf-8"));
        MDC.remove("costTime");
        MDC.remove("account");
        MDC.remove("threadUuid");
    }

    private void copyProperties(Object o,JSONObject js, String parentKey)throws Exception{
        for(Map.Entry<String, Object> entry:js.entrySet()){
            String key = entry.getKey();
            if(StringUtils.isNotBlank(parentKey)){
                key = parentKey+"."+entry.getKey();
            }
            if(entry.getValue() instanceof JSONObject){
                JSONObject subJson = ((JSONObject) entry.getValue());
                copyProperties(o,subJson,key);
            }else {

                Object value = BeanUtilsBean.getInstance().getPropertyUtils().getProperty(o, key);
                entry.setValue(value);
            }
        }
    }
}
